package create.he.builder;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.lang.Assert;
import create.he.common.Constant;
import create.he.entity.ControllerContent;
import create.he.entity.DaoContent;
import create.he.entity.EntityContent;
import create.he.entity.FieldAttribute;
import create.he.entity.GeneratorContent;
import create.he.entity.JDBCConfig;
import create.he.entity.ServiceContent;
import create.he.entity.ServiceImplContent;
import create.he.entity.TableColumnEntity;
import create.he.utils.JDBCUtil;
import create.he.utils.MapUtil;
import create.he.utils.StrUtil;
import lombok.extern.slf4j.Slf4j;

@Slf4j
public class GeneratorBuilder {
	/**
	 * 生成文件的上下文
	 */
	public GeneratorContent generator = new GeneratorContent();
	
	
	/**
	 * 字段
	 */
	private List<FieldAttribute> fieldAttributes = new ArrayList<>();
	/**
	 * 默认包路径
	 */
	private String defaultPackage= Constant.DEFAULT;
	/**
	 * 默认类名称
	 */
	private String defaultClassName = Constant.DEFAULT;
	/**
	 * 描述
	 */
	private String description;
	/**
	 * 表名称
	 */
	private String tableName;
	
	/**
	 * 文件输出路径
	 */
	private String outPath;
	
	
	/**
	 * 添加字段
	 * @param fieldName 数据表字段名称（ 自动去掉下划线并将字符串转换成驼峰命名规范 ）
	 * @param javaType 字段类型
	 * @return
	 */
	public GeneratorBuilder addField(String tableField,Class<?> javaType) {
		addField(StrUtil.unlineToCamel(tableField), tableField, javaType, null);
		return this;
	}
	/**
	 * 添加字段
	 * @param tableField 数据表字段名称（ 自动去掉下划线并将字符串转换成驼峰命名规范 ）
	 * @param javaType 	字段类型
	 * @param description	字段描述
	 * @return
	 */
	public GeneratorBuilder addField(String tableField,Class<?> javaType,String description) {
		addField(StrUtil.unlineToCamel(tableField), tableField, javaType, description);
		return this;
	}
	/**
	 * 添加字段 
	 * @param fieldName 字段名称
	 * @param tableField 数据库字段名称
	 * @param fieldType	字段类型
	 * @param	description	字段描述 
	 * @return
	 */
	public GeneratorBuilder addField(String fieldName,String tableField,Class<?> javaType,String description) {
		String f = null;
		if (javaType != null) {
			f = StrUtil.unlineToPascal(javaType.getSimpleName());
		}
		addField(fieldName,tableField,f,description);
		return this;
	}
	/**
	 * 添加字段 
	 * @param fieldName 字段名称
	 * @param tableField 数据库字段名称
	 * @param fieldType	字段类型
	 * @param	description	字段描述 
	 * @return
	 */
	private GeneratorBuilder addField(String fieldName,String tableField,String javaType,String description) {
		FieldAttribute f = new FieldAttribute();
		if (!cn.hutool.core.util.StrUtil.isAllBlank(fieldName.toString())) {
			f.setField(fieldName);
		}
		if (!cn.hutool.core.util.StrUtil.isAllBlank(tableField.toString())) {
			f.setTableField(tableField);
		}
		if (javaType != null) {
			f.setJavaType(javaType);
		}
		if (description != null) {
			f.setDescription(description);
		}
		fieldAttributes.add(f);
		return this;
	}
	public List<FieldAttribute> getFieldAttributes() {
		return this.fieldAttributes;
	}
	public GeneratorContent getGeneratorContent() {
		return this.generator;
	}
	
	
	/**
	 * 文件输出路径
			/gzqixun-tech-saas-tenant-system-dao/src/main/java
  	 */
	public GeneratorBuilder setOutPath(String outPath) {
		this.outPath = outPath;
		return this;
	}
	
	public String getOutPath() {
		return  outPath;
	}
	
	
	public GeneratorBuilder setEntity(EntityContent entity) {
		generator.setEntityContent(entity);
		return this;
	}
	public GeneratorBuilder setService(ServiceContent service) {
		generator.setServiceContent(service);
		return this;
	}
	public GeneratorBuilder setServiceImpl(ServiceImplContent serviceImpl) {
		generator.setServiceImplContent(serviceImpl);
		return this;
	}
	public GeneratorBuilder setDao(DaoContent dao) {
		generator.setDaoContent(dao);
		return this;
	}
	public GeneratorBuilder setController(ControllerContent controller) {
		generator.setControllerContent(controller);
		return this;
	}
	/**
	 * 设置默认包路径
	 * 
	 * @param defaultPackage
	 * @return
	 */
	public GeneratorBuilder setDefaultPackage(String defaultPackage) {
		this.defaultPackage = defaultPackage;
		return this;
	}
	/**
	 * 默认类名称
	 * @param defaultClassName
	 * @return
	 */
	public GeneratorBuilder setDefaultClassName(String defaultClassName) {
		this.defaultClassName = defaultClassName;
		return this;
	}
	/**
	 * 描述
	 * @return
	 */
	public GeneratorBuilder setDescription(String description) {
		this.description = description;
		return this;
	}
	
	/**
	 *  表名称
	 * @param description
	 * @return
	 */
	public GeneratorBuilder setTableName(String tableName) {
		this.tableName = tableName;
		return this;
	}
	
	/**
	 * 通过数据库表进行初始化
	 * @param tableName 数据库表名称
	 * @param jdbcConfig 数据库连接配置
	 * @return
	 */
	public GeneratorBuilder initByTable(String tableName,JDBCConfig jdbcConfig) {
		JDBCUtil jdbc = new JDBCUtil(jdbcConfig);
		// 获取字段信息
		List<Map<String ,Object>> findList =  jdbc.findList("show full COLUMNS from  "+tableName);
		List<TableColumnEntity> tableColumns= new ArrayList<TableColumnEntity>();
		findList.forEach(a -> {
			TableColumnEntity t= new TableColumnEntity();
				t.setColumnName(MapUtil.getString(a,"COLUMN_NAME"));
				t.setColumnDefault(MapUtil.getString(a,"COLUMN_DEFAULT"));
				t.setColumnComment(MapUtil.getString(a,"COLUMN_COMMENT"));
				t.setIsNullable(MapUtil.getString(a,"IS_NULLABLE"));
				t.setColumnType(MapUtil.getString(a,"COLUMN_TYPE"));
				t.setColumnKey(MapUtil.getString(a,"COLUMN_KEY"));
			tableColumns.add(t);
		});
		//添加到实体类上下文
		tableColumns.forEach(t->{ 
			addField(StrUtil.unlineToCamel(t.getColumnName()), t.getColumnName(), jdbc.getJavaTypeFromSQLType(t.getColumnType()), t.getColumnComment());
		});
		// 获取表结构信息，设置上下文
		Map<String, Object> map =  jdbc.getMap("select * from information_schema.tables where table_schema='"+jdbcConfig.getDB_NAME()+"'  and table_name='"+tableName+"'");
		this.tableName = tableName;
		this.description = MapUtil.getString(map, "TABLE_COMMENT");
		this.defaultClassName = StrUtil.unlineToPascal(MapUtil.getString(map, "TABLE_NAME"));
		return this;
	}
	
	public GeneratorContent builder() {
		Class classs[] = { EntityContent.class, ServiceContent.class, DaoContent.class, ServiceImplContent.class, ControllerContent.class };
		for (Class c : classs) {
			try {
				Class class1 = generator.getClass();
				Field[] fields = class1.getDeclaredFields();
				for (Field f : fields) {
					if (f.getGenericType().getTypeName().equals(c.getName())) {
						Object newInstance = c.newInstance();
						Method setClassName = c.getMethod("setClassName", String.class);
						Method setClassPackage = c.getMethod("setClassPackage", String.class);
						
						setClassName.invoke(newInstance, defaultClassName + c.getSimpleName().replace("Content", ""));
						setClassPackage.invoke(newInstance, defaultPackage);
						
						f.setAccessible(true);
						if(f.get(generator) !=null ) {
							// 为空的旧值不会覆盖新值
					        BeanUtil.copyProperties(f.get(generator),newInstance, CopyOptions.create().setIgnoreNullValue(true));
						} 
						
						f.set(generator, newInstance);
					}
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		
		EntityContent e = generator.getEntityContent();
			if(description !=null) {
				e.setDescription(description);
			}
			if(tableName !=null) {
				e.setTableName(tableName);
			}
			if(fieldAttributes.size()>0) {
				e.setFieldAttributes(fieldAttributes);
			}
			
			generator.setEntityContent(e);
			
			Assert.notBlank(this.tableName,"tableName不能为空", "tableName");
			Assert.notBlank(this.outPath,"outPath不能为空", "outPath");
			
		return generator;
	}
	
}
